<template>
  <component 
    v-if="isValidComponent"
    :is="dynamicComponent"
    v-bind="processedProps"
    @click="handleEvent('click')"
    @change="handleEvent('change')"
  >
    <template v-if="schema.children && schema.children.length">
      <RecursiveRenderer
        v-for="(child, index) in schema.children"
        :key="child.id || index"
        :schema="child"
        @action="handleChildAction"
      />
    </template>

    <template v-else-if="schema.props?.default">
      {{ schema.props.default }}
    </template>
  </component>

  <div v-else class="error-fallback">
    组件 {{ schema.component }} 渲染失败
  </div>
</template>

<script setup lang="ts">
import { computed, defineAsyncComponent } from 'vue'
import type { ComponentSchema } from '@/types'

interface Props {
  schema: ComponentSchema
}

const props = defineProps<Props>()

const emit = defineEmits<{
  action: [action: string, data?: any]
}>()

// 动态组件映射（文章中的动态渲染器实现）
const componentMap: Record<string, any> = {
  'd-button': defineAsyncComponent(() => import('vue-devui/button')),
  'd-table': defineAsyncComponent(() => import('vue-devui/table')),
  'd-card': defineAsyncComponent(() => import('vue-devui/card')),
  'd-input': defineAsyncComponent(() => import('vue-devui/input')),
  'd-select': defineAsyncComponent(() => import('vue-devui/select'))
}

const dynamicComponent = computed(() => {
  return componentMap[props.schema.component]
})

const isValidComponent = computed(() => {
  return !!dynamicComponent.value
})

// 处理Props，支持指令式交互（文章中的创新点）
const processedProps = computed(() => {
  const propsObj = { ...props.schema.props }

  // 处理事件绑定
  Object.keys(propsObj).forEach(key => {
    if (typeof propsObj[key] === 'string' && propsObj[key].startsWith('emit:')) {
      const action = propsObj[key].replace('emit:', '')
      propsObj[key] = () => emit('action', action)
    }
  })

  return propsObj
})

const handleEvent = (eventType: string) => {
  const actionKey = `on${eventType.charAt(0).toUpperCase() + eventType.slice(1)}`
  const action = props.schema.props?.[actionKey]

  if (typeof action === 'function') {
    action()
  } else if (typeof action === 'string' && action.startsWith('emit:')) {
    emit('action', action.replace('emit:', ''))
  }
}

const handleChildAction = (action: string, data?: any) => {
  emit('action', action, data)
}
</script>

<style scoped>
.error-fallback {
  padding: 8px;
  border: 1px dashed #ff4d4f;
  color: #ff4d4f;
  background: #fff2f0;
}
</style>